5.22
改进这章的 write 的减半本本, 接受用户名作为参数, 处理特殊情况, 显示欢迎信息
#include <stdio.h> #include <utmp.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <time.h> #define DEBUG char *peertty(struct utmp [], size_t); char *welcome(struct utmp[], size_t); int main( int argc, char **argv ) { if (argc != 2){ fprintf(stderr, "usage: %s [username]\n", argv[0]); return 1; } struct utmp buf, bufs[BUFSIZ]; struct stat info; int utmpfd, i, k = 0, reclen = sizeof(struct utmp); if ((utmpfd = open(UTMP_FILE, O_RDONLY)) == -1){ perror("read utmp "); return 2; } for (i = 0; i < BUFSIZ; i++){ if (read(utmpfd, &buf, reclen) == reclen){ if (buf.ut_type == USER_PROCESS && strcmp(buf.ut_user, argv[1]) == 0){ bufs[k] = buf; k++; } } } close(utmpfd); if (k == 0){ fprintf(stderr, "%s is not login\n", argv[1]); return 3; } char *devs = peertty(bufs, k); if (k > 1){ printf("%s logged in more than once; writing to: %s\n", argv[1], devs); } #ifdef DEBUG printf("%s\n", devs); #endif if (stat(devs, &info) == 0){ #ifdef DEBUG printf("%d-%d", info.st_mode, info.st_mode & (S_IWGRP | S_IWOTH)); #endif if ((info.st_mode & (S_IWGRP|S_IWOTH)) == 0){ fprintf(stderr, "%s is block the message\n", argv[1]); return 5; } }else{ perror("stat "); return 4; } int wfd; if ((wfd = open(devs, O_RDWR | O_APPEND)) == -1){ perror("open"); return 6; } char *wstr = welcome(bufs, k); if (write(wfd, wstr, sizeof(char) * strlen(wstr)) == -1){ perror("write "); return 9; } char c; while((c = getchar())){ if (write(wfd, &c, sizeof(c)) == -1){ perror("write"); return 8; } } return 0; } char *line2devpath(char *line) { char devs[13] = "/dev/"; strcat(devs, line); return strdup(devs); } char *peertty(struct utmp utmpbufs[], size_t t){ char *devs, *cur = ttyname(1); #ifdef DEBUG printf("size %ld\n", t); #endif if (t == 1){ return line2devpath(utmpbufs[0].ut_line); } unsigned int i; #ifdef DEBUG printf("cur tty %s\n", cur); #endif for (i = 0; i < t; i++){ devs = line2devpath(utmpbufs[i].ut_line); if (strcmp(devs, cur) != 0){ return devs; } } return line2devpath(utmpbufs[0].ut_line); } char *welcome(struct utmp ubufs[], size_t n) { char *curtty = ttyname(1), wstr[BUFSIZ]; time_t rawtime; unsigned int i; for (i=0; i < n; i++){ if (strcmp(line2devpath(ubufs[i].ut_line), curtty) == 0){ time(&rawtime); sprintf(wstr,"Message from %s@%s on %s at %s\n", ubufs[i].ut_user, ubufs[i].ut_host, ubufs[i].ut_line, ctime(&rawtime)); #ifdef DEBUG printf("wstr %s\n", wstr); #endif return strdup(wstr); } } }
5.23
编写mesg, 查看源码 mesg 就是关闭当前tty的 组和其他用户的写权限来实现
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/stat.h> int main( int argc, char **argv ) { if ((argc == 2 && strlen(argv[1]) == 1) && (argv[1][0] != 'y' && argv[1][0] != 'n')){ fprintf(stderr, "usage: %s y|n\n", argv[0]); return 1; } char *tty = ttyname(1); char r = 'n'; struct stat info; if (stat(tty, &info) == -1){ perror("stat"); return 1; } if (argc == 1){ if (info.st_mode & (S_IWGRP|S_IWOTH)){ r = 'y'; } printf("%s %c\n", argv[0], r); return 0; } if (argv[1][0] == 'y'){ if (chmod(tty,info.st_mode | S_IWGRP | S_IWOTH) == -1){ perror("chmod"); return 1; } }else { if (chmod(tty, info.st_mode & ~(S_IWGRP | S_IWOTH))){ perror("chmod"); return 1; } } return 0; }